"""
@Project:${2108a 人工智能}
@File:utils.py
@Author:周家昌
@Date:14:28
"""
import smtplib

# 邮件库
from email.mime.text import MIMEText    # 邮件内容
from email.mime.multipart import MIMEMultipart

import random

import jwt
import time
import os
import json
import datetime
from functools import wraps
from db import User_Model,database,Access_Model,Node_Model,User_Role_Model,Access_role_Model,Role_Model
import upyun
import peewee_async


class Page:
    def __init__(self,size):
        self.size = size
        self.database = peewee_async.Manager(database)

    # @property  # 将方法变成属性
    async def get_total_page(self,model,keyword,newfields):
        if keyword:
            mymodel = f'User_Model.{newfields}'
            mymodel = eval(mymodel)   # 实体化

            total = await self.database.count(model.select().where(mymodel.contains(keyword)))
        else:
            total = await self.database.count(model.select())
        if total % self.size == 0:
            total = total // self.size  # 整除
        else:
            total = total // self.size + 1
        return total  # 总页数


    async def get_list(self,page,model,table,keyword,newfields,od):

        start = (int(page) - 1) * self.size  # 分页的算法   m,n    m = (页码-1) * n
        if keyword:
            _sql = f' select * from  `{table}` where `{newfields}` like "%%'+ keyword +f'%%" order by (id) {od} limit {start},{self.size}'
        else:
            _sql = f""" select * from  `{table}` order by (id) {od} limit {start},{self.size}"""
        databaselist = await self.database.execute(model.raw(_sql))
        return databaselist

    # async def get_list(self, page, model, table):
    #     page = int(page)
    #
    #     # 分页算法
    #     start = (page - 1) * self.size
    #
    #     # 查询
    #     datalist = await self.database.execute(
    #         model.raw(' select * from `%s` limit %s,%s ' % (table, start, self.size)))
    #
    #     return datalist


class Upyun:
    def __init__(self,uid):
        self.uid = uid
        self.bd_path = './static/user%s'%uid
        self.path = '/static/%s/'%uid
        self.url = 'http://image-upyun-zjc.test.upcdn.net/static/%s/'%uid
        self.up = upyun.UpYun('image-upyun-zjc',username='zjc',password='uNHWjSszGCqvXWeThVwniYvQMRFVxU6N', timeout=60)
        # self.img = ['.png', '.jpg', '.jpeg', 'gif', '.jfif', '.jpeg']
        # self.video = ['.mp4', '.avi', '.mpv']

    def upload(self,filename):
        with open(self.bd_path+'/'+filename,'rb')as f:   # 上传文件 (自动创建对应目录)

            self.up.put(self.path + '/' + filename, f)


    def filelist(self):              # 获取目录下的文件
        try:
            res=self.up.getlist(self.path)
            return res
        except Exception as e:
            return []

    def delfile(self,filename):      # 删除指定文件
        self.up.delete(self.path+'/'+filename)

    def get_file(self,filename):
        return self.url + filename


class WriteFile:   # 文件管理类
    def __init__(self,uid):
        self.uid = uid
        self.path = './static/user%s' % uid
        self.img = ['.png','.jpg','.jpeg','gif','.jfif','.jpeg']
        self.video = ['.mp4','.avi','.mpv']
        self.webpath = 'http://localhost:8000/static/user%s/'%uid
    # 返回文件标签
    def filetype(self,filename):
        # 取后缀名
        fileback = os.path.splitext(filename)[-1]
        if fileback in self.img:
            return '<img width="100" src="%s%s">'%(self.webpath,filename)
        if fileback in self.video:
            return '<video width="200" src="%s%s">'%(self.webpath,filename)
    def createfile(self): # 创建文件夹
        if not os.path.exists(self.path):
            os.makedirs(self.path)
    def filelist(self):  # 文件列表
        if not os.path.exists(self.path):
            return []
        filelist = os.listdir(self.path)
        return filelist
    def del_file(self,filename):
        if os.path.exists(self.path + '/' + filename):
            file_path = self.path + '/' + filename
            os.remove(file_path)

    # def file(self,meta):
    #     path = './static/user%s'%self.uid
    #     if not os.path.exists(path):
    #         os.makedirs(path)
    #     filepath = path + '/' + meta['filename']
    #     with open(filepath, 'wb')as f:
    #         f.write(meta['body'])
    #     return filepath
    # # 文件列表
    # def get_file(self):
    #
    #     if not os.path.exists(self.path):
    #         return []
    #     list1 = os.listdir(self.path)
    #     list2 = []
    #     for i in list1:
    #         data = {'filename':i,'filepath':self.path +'/'+i}
    #         list2.append(data)
    #     return list2  # 该用户文件夹下的所有文件名
    #
    # def del_file(self,filename):
    #     path = './static/user%s' % self.uid
    #     file_path = path + '/' + filename
    #     os.remove(file_path)
    #     return 'ok'

# print(WriteFile(113).filetype('day1_配置python开发环境.mp4'))

def rbac_auth(func):
    @wraps(func)
    async def wrapper(self,*args,**kwargs):
        # 该用户的所有角色     多对多关系
        userrole = await self.application.objects.execute(User_Role_Model.select().where(User_Role_Model.uid==self._cuser.id))
        if not userrole:
            return self.finish({'errcode': 4, 'msg': '该用户没有角色权限'})
        # 该用户的所有角色的节点集合
        rids = [x.rid for x in userrole]

        nids = await self.application.objects.execute(Access_role_Model.select().where(Access_role_Model.rid.in_(rids)))
        if not nids:
            return self.finish({'errcode': 3, 'msg': '没有节点授权'})
        nids = [x.nid for x in nids]
        try:
            # 检索当前请求方式的节点id
            node = await self.application.objects.get(
                Node_Model.select().where(Node_Model.method == self.request.method))
        except Exception as e:
            print(e)
            return self.finish({'errcode': 2, 'msg': '该系统节点不存在'})
        if node.id not in nids:
            return self.finish({'errcode': 1, 'msg': '无操作权限'})
        await func(self, *args, **kwargs)
    return wrapper




# 权限判断
def acl_auth(nid=None):
    def decorator(func):
        @wraps(func)
        async def wrapper(self, *args, **kwargs):

            if self._cuser.id == 120:  # 超级用户  直接通过权限验证
                await func(self,*args,**kwargs)
            try:
                # 检索当前请求方式的节点id
                node = await self.application.objects.get(Node_Model.select().where(method = self.request.method))
            except Exception as e:
                return self.finish({'errcode': 400, 'msg': '该系统节点不存在'})
            nids = await self.application.objects.execute(Access_Model.select().where(Access_Model.uid==self._cuser.id))
            if not nids:
                return self.finish({'errcode':400,'msg':'无操作权限'})
            else:
                nids = [x.nid for x in nids]
            if node.id not in nids:
                return self.finish({'errcode': 400, 'msg': '无操作权限'})
            await func(self, *args, **kwargs)
        return wrapper
    return decorator

# token认证装饰器
def jwt_token(func):
    @wraps(func)
    async def wrapper(self,*args,**kwargs):

        token = self.get_argument('token', None)
        if not token:
            return self.finish({'errcode': '1', 'msg': '没有权限,token不存在'})
        try:
            user_jwt = MyJwt().decode(token)
        except Exception as e:
            print(e)
            return self.finish({'errcode': '1', 'msg':str(e)})
        try:
            user = await self.application.objects.get(User_Model.select().where(User_Model.id==user_jwt.get('id')))
            self._cuser = user    # 将找到的用户对象存入self实例中

        except Exception as e:
            print('******',e)
            return self.finish({'errcode': '1', 'msg':'用户不存在' })
        await func(self, *args, **kwargs)
    return wrapper

# token类
class MyJwt:
    def __init__(self):
        # 初始化密钥（盐）
        self.password = '123456fds'

    # 生命周期token
    def encode_time(self,userinfo):
        payload = {
            # 当前时间点 加上一个时间周期
            'exp':int((datetime.datetime.now() + datetime.timedelta(seconds=60*60*24*30*3)).timestamp()),
            'data':userinfo
        }
        encoded_jwt = jwt.encode(payload, self.password, algorithm='HS256')

        return encoded_jwt

    # 生成token
    def encode(self,userinfo):
        encoded_jwt = jwt.encode(userinfo,self.password,algorithm='HS256')

        return encoded_jwt

    # 解密token
    def decode(self,token):

        decoded_json = jwt.decode(token,self.password,algorithms=['HS256'])

        return decoded_json

# 随机码生成器
def create_code(abc=True,codelen=6):  # 是否需要字母   验证码的长度默认
    if abc:
        base_str = '0123456789qwertyuiopasdfghjklzxcvbnm'
    else:
        base_str = '0123456789'
    return ''.join([random.choice(base_str) for _ in range(codelen)])
# 邮件类
class EmailTool:

    def __init__(self):
        # 发送者邮箱
        self.fromemail = '1252878935@qq.com'
        # 发送者邮箱emtp密钥
        self.pwd = 'dnwstzatpcnkgfbf'
    # 邮箱发送方法 发送激活链接或者激活码
    def sendemail(self,tomail,code):
        # 设置邮件主体
        msg = MIMEMultipart()
        # 设置标题
        msg['Subject'] = '社交平台邮箱验证'
        # 发件人
        msg['From'] = self.fromemail
        # 收件人
        msg['To'] = tomail

        # 设置邮件文本
        part = MIMEText('验证码为：%s'%code,'html','utf-8')
        msg.attach(part)

        # 登录qq邮箱
        s = smtplib.SMTP_SSL('smtp.qq.com',465)
        s.login(self.fromemail,self.pwd)
        # 调用发送方法
        s.sendmail(self.fromemail,tomail,msg.as_string())
        # 关闭邮箱连接
        s.close()

# 文件操作类
class MyFile:

    def check(self,filename):
        if self.find(r'./',filename):  # 判断文件是否存在
            text = self.read(filename)
            text = json.loads(text)
            now_time = int(time.time())
            num_time = text['time']
            my_time = now_time - num_time
            if my_time <= 30:
                if text['num'] >= 5:
                    self.delfile(filename)
                    return False
            else:
                self.delfile(filename)
        return True


    def read(self,filename):  # 读文件
        text = ''
        with open(filename,'r',encoding='utf-8') as f:
            text = f.read()
        return text


    def write(self,filename): # 写文件
        res = self.find(r'./',filename)
        if res:
            text = self.read(filename)
            text = json.loads(text)
            text['num'] += 1
            with open(filename,'w',encoding='utf-8')as f:
                f.write(json.dumps(text))
        else:
            mytime = int(time.time())
            text = '{"time":%s,"num":1}'%mytime
            with open(filename,'w',encoding='utf-8')as f:
                f.write(text)

    def find(self,start,filename): # 查找文件
        for relpath,dirs,files in os.walk(start):  # 查找该目录文件
            if filename in files:
                return True
            else:
                return False

    def delfile(self,filename):
        if os.path.exists(filename):
            os.remove(filename)













if __name__ == '__main__':
    f = MyFile()
    # print(f.read('bbb.txt'))
    # f.write('bbb.txt')
    # print(f.find(r'./','bbb.txt'))

    # et = EmailTool()
    # et.sendemail('2722123101@qq.com ','666')
    # myjwt = MyJwt()
    # print(myjwt.encode({'id':1,'email':'123456@qq.com'}))
    # print(myjwt.decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZW1haWwiOiIxMjM0NTZAcXEuY29tIn0.mHGcID9t-fFt4xyFmpubZVgc20TOvd7xKYgtb0aiOY0'))
    # print('*')
    # print(create_code())
